<?php
class StatisticsService extends AbstractService
{
    /**
     * @var StatisticsService
     */
    private static $instance;

    /**
     * 登录时使用的token
     * @var array $token
     */
    private $token;

    /**
     * Get the instance of LogService.
     *
     * @return StatisticsService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new StatisticsService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    protected function __construct()
    {
        parent::__construct();
    }

    /**
     * 处理创建时的逻辑
     *
     * @param int $shardId
     * @return void
     */
    public function handleCreate($shardId)
    {

    }

    /**
     * 保存游戏内的唯一登录标识
     * @param int $userId
     * @param string $token
     * @return mixed
     */
    public function saveToken($userId, $token)
    {
        $this->token[$userId] = $token;
    }

    /**
     * 游戏内的唯一登录标识
     * @param $userId
     * @return mixed
     */
    private function getToken($userId)
    {
        if (!isset($this->token[$userId]) || empty($this->token[$userId])) {
            $this->token[$userId] = SzContextFactory::get()->getStaticCache($userId)->get(GameConst::CACHE_KEY_TOKEN . $userId);
        }
        return $this->token[$userId];
    }

    /**
     * 处理登录时的逻辑
     *
     * @param int $userId
     * @param ModuleProfileVo $profile
     * @return void
     */
    public function handleLogin($userId, $profile = null)
    {
        StatisticsService::get()->logItemInfo($userId, $profile);
    }

    /**
     * 提供Service层的所有数据
     *
     * @param int $shardId
     * @return mixed
     */
    public function info($shardId)
    {
        return true;
    }

    /**
     * 保存日志
     *
     * @param int $userId
     * @param string $act
     * @param array $data default array()
     * @param ModuleProfileVo $profile default null
     * @param ModuleProfileInfoVoList $profileInfoList default null
     * @param string $deviceId default ''
     * @return boolean
     */
    public function saveLog($userId, $act, $data = array(), $profile = null, $profileInfoList = null, $deviceId = '')
    {
        // 用户基础信息
        if (is_null($profile)) {
            $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        }
        list($tid, $item, $value, $value2) = $this->formatData($act, $data, $profile);
        // 保存数据采集
        ModuleStatistics::get()->saveLog(
            // FIXME: USE PLATFORM ID INSTEAD OF userId WHEN THE GAME WILL PUT ONLINE
            empty($deviceId) ? $userId : $deviceId, // platformId
            $profile->getToken(),                   // cash
            PayService::get()->getMoney($userId),   // gold
            $profile->getLevel(),                   // level
            $profile->getRegisterTime(),            // rTime
            $this->getToken($userId), // session 游戏内的唯一登录标识,
            $act, $tid, $item, $value, $value2
        );
        return true;
    }

    /**
     * 保存工会日志
     * @param $act
     * @param $rtime
     * @param array $data
     * @return bool
     */
    public function saveGuildLog($act,$rtime, $data = array())
    {
        $tid    = SzUtility::checkArrayKey('tid', $data['clientData']) ? $data['clientData']['tid'] : '';
        $item   = SzUtility::checkArrayKey('item', $data['clientData']) ? $data['clientData']['item'] : '';
        $value  = SzUtility::checkArrayKey('value', $data['clientData']) ? $data['clientData']['value'] : 0;
        $value2 = SzUtility::checkArrayKey('value2', $data['clientData']) ? $data['clientData']['value2'] : 0;

        ModuleStatistics::get()->saveLog(
        // FIXME: USE PLATFORM ID INSTEAD OF userId WHEN THE GAME WILL PUT ONLINE
            GameConst::GUILD_LOG_DATA_KEY, // platformId
            0, // cash
            0, // gold
            0, // level
            $rtime, // rTime
            0, // session 游戏内的唯一登录标识,
            $act, $tid, $item, $value, $value2
        );
        return true;
    }

    /**
     * 根据Action格式化数据
     *
     * @param string $act
     * @param array $data
     * @param ModuleProfileVo $profile
     * @return array()
     */
    private function formatData($act, $data, $profile)
    {
        // 根据act，处理数据采集逻辑
        switch ($act) {
            //case GameConst::LOG_TYPE_VISIT: // 玩家登录 , 打开页面
            case GameConst::LOG_TYPE_INIT_FINISHED: //游戏初始化完成
            //case GameConst::LOG_TYPE_INSTALL: // 新用户安装
                $sourceViaFeed = $this->getSourceViaFeed();
                $sourceViaRequest = $this->getSourceViaRequest();
                $item = $this->getPlatformSource(GameService::get()->getLang($profile->getUserId()));
                $tid = ($sourceViaFeed) ? $sourceViaFeed : $sourceViaRequest;
                break;
            default:
                // 从前端获得的数据，需要进行截取字段，文字过长会导致数据部门解析报错
                if ($act == GameConst::LOG_TYPE_ERROR) {
                    $value  = SzUtility::checkArrayKey('value', $data['clientData']) ? $data['clientData']['value'] : '';
                    $value2 = SzUtility::checkArrayKey('value2', $data['clientData']) ? $data['clientData']['value2'] : '';

                    $data['clientData']['value']   = substr($value, 0, 255);
                    $data['clientData']['value2']  = substr($value2, 0, 255);
                }

                // Flash传递进来的logData, 则不需要根据act处理采集逻辑
                if (SzUtility::checkArrayKey('clientData', $data)) {
                    $tid    = SzUtility::checkArrayKey('tid', $data['clientData']) ? $data['clientData']['tid'] : '';
                    $item   = SzUtility::checkArrayKey('item', $data['clientData']) ? $data['clientData']['item'] : '';
                    $value  = SzUtility::checkArrayKey('value', $data['clientData']) ? $data['clientData']['value'] : 0;
                    $value2 = SzUtility::checkArrayKey('value2', $data['clientData']) ? $data['clientData']['value2'] : 0;
                }
                break;
        }

        // 初始化
        return array(
            (isset($tid))    ? $tid    : '',
            (isset($item))   ? $item   : '',
            (isset($value))  ? $value  : 0,
            (isset($value2)) ? $value2 : 0,
        );
    }

    /**
     * Get source via feed
     *
     * @return string
     */
    private function getSourceViaFeed()
    {
        $feedId = SzParam::getReqParam('feedId');
        if (!empty($feedId) && $feedId) {
            return 'f_' . $feedId;
        } else {
            return null;
        }
    }

    /**
     * Get source via request
     *
     * @return string
     */
    private function getSourceViaRequest()
    {
        $requestIds = explode(',', SzParam::getReqParam('request_ids'));
        if (!empty($requestIds) && is_array($requestIds)) {
            return 'r_' . array_shift($requestIds);
        } else {
            return null;
        }
    }

    /**
     * Get platform source
     *
     * @param string $lang
     * @return string
     */
    private function getPlatformSource($lang)
    {
        $keyArray = array('fb_locale', 'fb_source', 'fb_appcenter', 'fbs', 'ref', 'source', 'oid', 'fb_bmpos', 'fb_ref', 'sc', 'ad_id', 'app_request_type', 'fb_action_types', 'feedId', 'group', 'version', 'piclick');
        $urlPara = '';
        foreach (SzParam::getWholeRequest() as $key => $info) {
            if (in_array($key, $keyArray)) {
                $urlPara .= $key . ':' . $info . '|';
            }
        }

        return "sz_para:{branch:0|lang:{$lang}|}|url_para:{{$urlPara}}|";
    }

    /**
     * 根据产出物品配置组装tid
     *
     * @param array $output
     * @return string $tid
     * <pre>
     *     $output => array(
     *          itemDefId => count,
     *    );
     * </pre>
     */
    public function buildTidWithItemArray($output){
        $tid = '';
        foreach($output as $itemDefId => $count) {
            $tid = $this->mergeTid($tid, $itemDefId, $count);
        }

        return $tid;
    }

    /**
     * Merge Tid
     *
     * @param string $tid default ''
     * @param int $entityId
     * @param int $count
     * @return string
     */
    public function mergeTid($tid = '', $entityId, $count)
    {
        $tid .= $entityId . ':' . abs($count) . '|';
        return $tid;
    }

    /**
     * 拼装数据中心tid
     *
     * @param string $logType
     * @param array $subIds
     * @param array $modules
     * @return string
     */
    public function buildTid($logType, $subIds, $modules = array())
    {
        $action = GameConst::ENTITY_ACTION_GET;
        if ($logType == GameConst::LOG_TYPE_RESOURCE_INPUT) {
            $action = GameConst::ENTITY_ACTION_CONSUME;
        }

        $tid = '';
        foreach ($subIds as $subId => $count) {
            $module = (SzUtility::checkArrayKey($subId, $modules)) ? $modules[$subId] :GameConst::ENTITY_TYPE_ITEM;
            $tid .= EntityService::get()->buildEntityId($action, $module, $subId) . ':' . abs($count) . '|';
        }

        return $tid;
    }

    /**
     * 数据采集获取玩家仓库数据
     *
     * @param int $userId
     * @param ModuleProfileVo $profile
     * @return void
     */
    public function logItemInfo($userId, $profile = null)
    {
        if (GameService::get()->isDailyFirstLogin($userId, $profile) == false) {
            return;
        }

        if (!$profile) {
            $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        }

        $tid = '';
        $tid = $this->mergeTid($tid, 'coin', $profile->getToken());
        $tid = $this->mergeTid($tid, 'cash', PayService::get()->getMoney($userId));
        $tid = $this->mergeTid($tid, 'level', $profile->getLevel());

        $warehouseLevel = WarehouseService::get()->getWarehouseLevel($userId);
        foreach ($warehouseLevel as $warehouseId => $level) {
            $tid = $this->mergeTid($tid, $warehouseId, $level);
        }

        if ($tid) {
            // 记录日志：记录库存物品每日首次登录
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ITEM_INFO, array(
                'clientData' => array(
                    'tid' => $tid,
                )
            ), $profile);
        }
    }
}